package com.xzcedu.reflection;

import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * @author 徐州城
 * @version 1.0
 * 演示如何通过反射获取类的结构信息
 */
public class ReflectionUtils {
    //第一组方法API
    @Test
    public void api_01() throws ClassNotFoundException {

        //得到Class 对象
        Class<?> personCls = Class.forName("com.xzcedu.reflection.Person");
        //1. getName：获取全类名
        System.out.println(personCls.getName());

        //2. getSimpleName：获取简单类名
        System.out.println(personCls.getSimpleName());

        //3. getFields：获取所有public修饰的属性，包含本类以及父类的
        Field[] field = personCls.getFields();
        for (Field f : field) {
            System.out.println("本类以及父类的属性 = " + f.getName());
        }

        //4. getDeclareFields：获取本类中所有属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类所有属性 = " + declaredField.getName());
        }

        //5. getMethods：获取所有public修饰的方法，包含本类以及父类的
        Method[] methods = personCls.getMethods();
        for (Method method : methods) {
            System.out.println("本类及父类的方法 = " + method.getName());
        }

        //6. getDeclaredMethods：获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类所有的方法 = " + declaredMethod.getName());
        }

        //7. getConstructors：获取所有public修饰的构造器，包含本类
        Constructor<?>[] constructors = personCls.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println("本类的构造器及父类构造器 = " + constructor.getName());
        }

        //8. getDeclaredConstructors：获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("本类所有的构造器 = " + declaredConstructor.getName());//这里只是输出名字
        }

        //9. getPackage：以Package形式返回 包信息
        System.out.println(personCls.getPackage());

        //10. getSuperClass：以Class形式返回父类信息
        System.out.println("父类的Class对象 = " + personCls.getSuperclass());

        //11. getInterfaces：以Class[] 形式返回接口信息
        Class<?>[] interfaces = personCls.getInterfaces();
        for (Class<?> anInterface : interfaces) {
            System.out.println("接口信息 = " + anInterface);
        }

        //12. getAnnotations：以Annotation[] 形式返回注解信息
        Annotation[] annotations = personCls.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println("注解信息 = " + annotation);
        }
    }

    @Test
    public void api_02() throws ClassNotFoundException {

        //得到Class 对象
        Class<?> personCls = Class.forName("com.xzcedu.reflection.Person");
        //getDeclaredFields(): 获取本类所有的属性
        Field[] declaredFields = personCls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println("本类所有属性 = " + declaredField.getName()
                    + "\t\t该属性的修饰符 = " + declaredField.getModifiers()
                    + "\t\t该属性的类型 = " + declaredField.getType());
        }

        //getDeclaredMethods：获取本类中所有方法
        Method[] declaredMethods = personCls.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println("本类所有的方法 = " + declaredMethod.getName()
                    + "\t\t该方法的访问修饰符值 = " + declaredMethod.getModifiers()
                    + "\t\t该方法返回类型 = " + declaredMethod.getReturnType());

            //输出当前这个方法的形参数组情况
            Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该方法的形参类型 = " + parameterType);
            }
        }

        //getDeclaredConstructors：获取本类中所有构造器
        Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            System.out.println("========================");
            System.out.println("本类所有的构造器 = " + declaredConstructor.getName());//这里只是输出名字

            Class<?>[] parameterTypes = declaredConstructor.getParameterTypes();
            for (Class<?> parameterType : parameterTypes) {
                System.out.println("该构造器的形参类型 = " + parameterType);
            }
        }


    }
}

class A {
    public String hobby;

    public A() {
    }
}

@Deprecated
class Person extends A implements IA, IB {
    //属性
    public String name;
    protected int age;
    String job;
    private double sal;

    public Person() {

    }

    public Person(String name) {
    }

    private Person(int age, String name) {
    }

    //方法
    public void m1(String name, int age) {
    }

    protected String m2() {
        return null;
    }

    void m3() {
    }

    private void m4() {
    }
}

interface IA {
}

interface IB {
}